package fiuba.algo3.algothief;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class VistaConsola {

	private static boolean balazo = false;
	private static boolean cuchillazo = false;
	private static boolean victoria = false;
	private static boolean derrota = false;
	private int opcion;
	private Juego juego;
	private Scanner sc;
	private boolean terminoElCaso;

	public static void main(String[] args) {
		VistaConsola vc = new VistaConsola();
		vc.terminoElCaso = false;
		vc.menuPrincipal();
	}

	
	private void menuPrincipal() {
		System.out.println("Algo-Thief");
		System.out.println();
		System.out.println("1- Nuevo Juego");
		System.out.println("2- Cargar Juego");
		System.out.println("3- Salir");
		sc = new Scanner(System.in);
		opcion = Controlador.tomarOpcion(sc,3);
		if (opcion == 1) {
			menuNuevoJuego();
			menuCiudad();
		} else if (opcion == 2) {
			menuCargarJuego();
			menuCiudad();
		}
		sc.close();
	}
	

	private void menuNuevoJuego() {
		System.out.print("Ingrese su nombre: ");
		String nombre = Controlador.tomarString(sc);
		juego = new Juego(nombre);
		juego.armarCaso(new AlarmaGanarJuego(), new AlarmaRecibiBalazo(), new AlarmaMeAcuchillaron());
	}

	
	private void menuCargarJuego() {
		String nombreArchivo;
		System.out.print("Ingrese el nombre del juego guardado: ");
		nombreArchivo = Controlador.tomarString(sc);
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		Document doc = db.newDocument();
		File archivo = null;
		archivo = new File(nombreArchivo);
		try {
			doc = db.parse(archivo);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		doc.getDocumentElement().normalize();
		this.juego = Juego.hidratar(doc);
	}

	
	private void menuCiudad() {
		do {
			if (!this.terminoElCaso)
			{
				encabezado();
				System.out.println("Ciudad: " + juego.getJugador().getCiudadActual().getNombre());
				System.out.println("Elija a donde desea ir:");
				System.out.println();
				System.out.println("1- " + juego.getJugador().getCiudadActual().getLugar(0).getNombre());
				System.out.println("2- " + juego.getJugador().getCiudadActual().getLugar(1).getNombre());
				System.out.println("3- " + juego.getJugador().getCiudadActual().getLugar(2).getNombre());
				System.out.println("4- Viajar");
				System.out.println("5- Emitir orden de Arresto");
				System.out.println("6- Guardar y salir");
				opcion = Controlador.tomarOpcion(sc,6);
				if ((opcion == 1) || (opcion == 2) || (opcion == 3))
					menuPista(opcion);
				else if (opcion == 4)
					menuViaje();
				else if (opcion == 5)
					this.menuPedirOrdenDeArresto(juego.getJugador().getInterpol());
				else if (opcion == 6)
					menuGuardarJuego();
			}
			else
			{
				this.terminoElCaso = false;
				menuContinuarConNuevoCaso();
				opcion = 6;
			}
		} while (opcion != 6);
	}
	

	private void menuContinuarConNuevoCaso() {
		System.out.println("Elija lo que desea hacer:");
		System.out.println();
		System.out.println("1- Continuar con un nuevo caso");
		System.out.println("2- Guardar y salir");
		System.out.println("3- Salir sin guardar");
		opcion = Controlador.tomarOpcion(sc,3);
		if (opcion == 1)
		{
			juego.nuevoCaso(new AlarmaGanarJuego(), new AlarmaRecibiBalazo(), new AlarmaMeAcuchillaron());
			menuCiudad();
		}
		else if (opcion == 2)
		{
			juego.nuevoCaso(new AlarmaGanarJuego(), new AlarmaRecibiBalazo(), new AlarmaMeAcuchillaron());
			menuGuardarJuego();
		}
	}

	private void menuGuardarJuego() {
		System.out.print("Ingrese un nombre para el juego a guardar: ");
		String nombreArchivo = Controlador.tomarString(sc);
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		try {
			db = dbf.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		Document doc = db.newDocument();
		Element juegoSerializado = this.juego.serializar(doc);
		doc.appendChild(juegoSerializado);
		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		Transformer transformer = null;
		try {
			transformer = transformerFactory.newTransformer();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		}
		DOMSource source = new DOMSource(doc);
		File archivoDestino = new File(nombreArchivo);
		StreamResult result = new StreamResult(archivoDestino);
		try {
			transformer.transform(source, result);
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}
	

	private void menuViaje() {
		ArrayList<Ciudad> ciudades = new ArrayList<Ciudad>();
		encabezado();
		System.out.println("Elija a que ciudad desea viajar:");
		System.out.println();
		int nAzaroso = 1 + (int) (Math.random() * 3);
		Ciudad ciudad = null;
		for (int i = 1; i <= 3; i = i + 1) {
			if (i != nAzaroso) {
				ciudad = juego.getCaso().getCiudadAleatoriaListaNoVisitadaCriminal(ciudad);
				ciudades.add(ciudad);
				System.out.println(Integer.toString(i) + "- "
						+ ciudades.get(i - 1).getNombre());
			} else {
				int indice = juego.getCaso().getCriminal().getCiudadesVisitadas().indexOf(juego.getJugador().getCiudadActual());
				if (indice == juego.getCaso().getCriminal().getCiudadesVisitadas().size()-1) 
					indice = 0;
				ciudades.add(juego.getCaso().getCriminal().getCiudadesVisitadas().get(indice + 1));
				System.out.println(Integer.toString(i) + "- "+ ciudades.get(i - 1).getNombre());
			}
		}
		System.out.println("4- Volver a la ciudad");
		opcion = Controlador.tomarOpcion(sc,4);
		if ((opcion == 1) || (opcion == 2) || (opcion == 3))
			try {
				juego.getJugador().viajar(ciudades.get(opcion - 1));
			} catch (TeQuedasteSinTiempo e) {
				System.out
						.println("No tiene tiempo suficiente para viajar a esa ciudad");
			}
	}
	

	private void encabezado() {
		System.out.println(this.juego.getJugador().getRango() + " " + this.juego.getJugador().getNombre());
		System.out.println("Numero de casos resueltos: " + juego.getCantidadDeCasosResueltos());
		System.out.println("Tiempo restante: " + this.juego.getJugador().getTiempoRestante());
	}
	

	private void menuPista(int numero) {
		try {
			Pista pista = juego.getJugador().pedirPistaEnLugar(numero);
			encabezado();
			System.out.println(juego.getJugador().getCiudadActual().getLugar(numero - 1).getNombre());
			System.out.println("Pista: ");
			System.out.println();
			if (balazo) {
				System.out.println("Ha recibido un balazo al entrar al lugar. Pierde 8 horas curandose.");
				balazo = false;
			} else if (cuchillazo) {
				System.out.println("Ha recibido un cuchillazo. Pierde 4 horas curandose.");
				cuchillazo = false;
			} else if (victoria) {
				System.out.println("Ha atrapado al ladron! Felicitaciones!");
				victoria = false;
				this.terminoElCaso = true;
			} else if (derrota) {
				System.out.println("El ladron se ha escapado por no tener orden de arresto contra "+juego.getCaso().getCriminal().getNombre()+".");
				derrota = false;
				this.terminoElCaso = true;
			} else
				System.out.println(pista.getContenido());
			System.out.println();
		} catch (TeQuedasteSinTiempo e) {
			System.out.println("No tiene tiempo suficiente para visitar este lugar.");
		}
		System.out.print("Presione ENTER para salir de este lugar...");
		Controlador.esperarEnter();
	}
	
	
	private String menuSexos(Interpol interpol){
		String sexo="";
		System.out.println("ingrese sexo:");
		int i=0;
		for(i=0;i<interpol.getCantidadDeSexos();i++){
			System.out.println((i+1) + "-" + interpol.getSexo(i));
		}
		System.out.println((i+1) + "- Desconocido");
		int opcion = Controlador.tomarOpcion(sc,i+1);
		opcion--;
		if(opcion>=interpol.getCantidadDeSexos()){
			sexo="";
		}else{
			sexo=interpol.getSexo(opcion);
		}
		return sexo;
	}
	
	
	private String menuPelos(Interpol interpol){
		int i=0;
		String pelo;
		System.out.println("ingrese cabello:");
		for(i=0;i<interpol.getCantidadDePelos();i++){
			System.out.println((i+1) + "-" + interpol.getPelo(i));
		}
		System.out.println((i+1) + "- Desconocido");
		int opcion = Controlador.tomarOpcion(sc,i+1);
		opcion--;
		if(opcion>=interpol.getCantidadDePelos()){
			pelo="";
		}else{
			pelo=interpol.getPelo(opcion);
		}
		return pelo;
	}
	
	
	private String menuSenias(Interpol interpol){
		int i=0;
		String senia;
		System.out.println("ingrese senia:");
		for(i=0;i<interpol.getCantidadDeSenias();i++){
			System.out.println((i+1) + "-" + interpol.getSenia(i));
		}
		System.out.println((i+1) + "- Desconocido");
		int opcion = Controlador.tomarOpcion(sc,i+1);
		opcion--;
		if(opcion>=interpol.getCantidadDeSenias()){
			senia="";
		}else{
			senia=interpol.getSenia(opcion);
		}
		return senia;
	}
	
	
	private String menuVehiculos(Interpol interpol){
		int i=0;
		String vehiculo;
		System.out.println("ingrese vehiculo:");
		for(i=0;i<interpol.getCantidadDeVehiculos();i++){
			System.out.println((i+1) + "-" + interpol.getVehiculo(i));
		}
		System.out.println((i+1) + "- Desconocido");
		int opcion = Controlador.tomarOpcion(sc,i+1);
		opcion--;
		if(opcion>=interpol.getCantidadDeVehiculos()){
			vehiculo="";
		}else{
			vehiculo=interpol.getVehiculo(opcion);
		}
		return vehiculo;
	}
	
	
	private String menuHobbies(Interpol interpol){
		int i=0;
		String vehiculo;
		System.out.println("ingrese hobby:");
		for(i=0;i<interpol.getCantidadDeHobbies();i++){
			System.out.println((i+1) + "-" + interpol.getHobby(i));
		}
		System.out.println((i+1) + "- Desconocido");
		int opcion = Controlador.tomarOpcion(sc,i+1);
		opcion--;
		if(opcion>=interpol.getCantidadDeHobbies()){
			vehiculo="";
		}else{
			vehiculo=interpol.getHobby(opcion);
		}
		return vehiculo;
	}
	
	
	private void menuPedirOrdenDeArresto(Interpol interpol) {
		String sexo = "", pelo = "", senia = "", hobby = "", vehiculo = "";
		System.out.println();	
		System.out.println();
		sexo=menuSexos(interpol);
		System.out.println();
		pelo=menuPelos(interpol);
		System.out.println();
		senia=menuSenias(interpol);
		System.out.println();
		vehiculo=menuVehiculos(interpol);
		System.out.println();
		hobby=menuHobbies(interpol);
		ArrayList<String> nombresDeCriminalesAMostrar=this.juego.getJugador().emitirOrdenDeArresto(sexo, hobby, pelo, senia, vehiculo);
		if (nombresDeCriminalesAMostrar.size()==1) {
			System.out.println();
			System.out.print("La orden ha sido emitida contra " + nombresDeCriminalesAMostrar.get(0));
			System.out.println();
		}else if(nombresDeCriminalesAMostrar.size()>1){
			System.out.println("Los criminales que cumplen con las caracteristicas ingresadas son: ");
			System.out.println();
			for(int i=0;i<nombresDeCriminalesAMostrar.size();i++){
				System.out.println(nombresDeCriminalesAMostrar.get(i));
			}
		}else{
			System.out.println("No se encontro ningun criminal que cumpla con las caracteristicas ingresadas.");
		}
		System.out.print("Presione ENTER para terminar...");
		Controlador.esperarEnter();
	}
	

	public static void mostrarBalazo() {
		balazo = true;
	}

	
	public static void mostrarCuchillazo() {
		cuchillazo = true;
	}

	
	public static void mostrarVictoria() {
		victoria = true;
	}

	
	public static void mostrarDerrota() {
		derrota = true;
	}

}
